package controllers

import (
	comm "com.wangzhumo.lottery/common"
	"com.wangzhumo.lottery/conf"
	"com.wangzhumo.lottery/models"
	"com.wangzhumo.lottery/utils"
	"fmt"
	"log"
)

// GetLucky 抽奖
func (c *IndexController) GetLucky() map[string]interface{} {
	response := make(map[string]interface{})
	response["code"] = 0
	response["msg"] = ""

	// 1.验证用户登录
	loginUser := comm.GetLoginUser(c.Ctx.Request())
	if loginUser == nil || loginUser.UID < 1 {
		response["code"] = 422
		response["msg"] = "请先登录后再来抽奖"
		return response
	}
	// 2.用户抽奖分布式锁 - 不会大范围的影响其他用户
	ok := utils.LockUser(loginUser.UID)
	if ok {
		// 2.1加锁成功,记得解锁
		defer utils.UnLockUser(loginUser.UID)
	} else {
		// 2.2加锁失败，已经在抽奖了
		response["code"] = 5001
		response["msg"] = "抽奖中，请稍后再试"
		return response
	}

	// 3.验证用户今日参与次数
	// 比较频繁，加入redis缓存中.
	userCount := utils.IncrUserLuckyNum(loginUser.UID)
	if userCount >= conf.UserPrizeMax {
		response["code"] = 5001
		response["msg"] = "已达参与上限，请明日在来参加"
		return response
	} else {
		checkOK := c.checkUserDay(loginUser.UID, userCount)
		if !checkOK {
			response["code"] = 5001
			response["msg"] = "已达参与上限，请明日在来参加"
			return response
		}
	}

	// 4.验证ip今日参与次数
	clientIp := comm.ClientIp(c.Ctx.Request())
	ipCount := utils.IncrIpCount(clientIp)
	// 这里是判断最大参与次数
	if ipCount > conf.IpLimitMax {
		response["code"] = 5002
		response["msg"] = "当前IP已达上限，请明天再来参与"
		return response
	}

	limitBlack := false // 黑名单
	// 这里是在最大参与次数中，最大可以中奖次数的判断
	if ipCount > conf.IpPrizeMax {
		limitBlack = true
	}

	// 5.验证ip黑名单
	var ipBlack *models.IpBlack
	if !limitBlack {
		ok, ipBlack = c.checkBlackIp(clientIp)
		if !ok {
			fmt.Println("命中IP黑名单", clientIp, limitBlack)
			limitBlack = true
		}
	}

	// 6.验证用户黑名单
	var userBlack *models.UserBlack
	if !limitBlack {
		ok, userBlack = c.checkBlackUser(loginUser.UID)
		if !ok {
			fmt.Println("命中用户黑名单", loginUser.UID, limitBlack)
			limitBlack = true
		}
	}

	// 7.给用户分配抽奖码
	prizeCode := comm.Random(10000)
	fmt.Println("User PrizeCode = ", prizeCode)

	// 8.匹配是否中奖
	prizeGift := c.lottery(prizeCode, limitBlack)
	fmt.Println("User prizeGift = ", prizeGift)
	if prizeGift == nil || (prizeGift.PrizeNum > 0 && prizeGift.LeftNum <= 0) {
		// 不能发奖
		response["code"] = 2004
		response["msg"] = "没有中奖，再来一次"
		return response
	}

	// 9.有限制的奖品发放（数量啊什么的）
	if prizeGift.PrizeNum > 0 {
		if utils.PrizeCachePoolNum(prizeGift.Id) <= 0 {
			response["code"] = 2005
			response["msg"] = "没有中奖，再来一次"
			return response
		}
		ok = utils.PrizeGift(prizeGift.Id, prizeGift.LeftNum)
		if !ok {
			// 不能发奖
			response["code"] = 2005
			response["msg"] = "没有中奖，再来一次"
			return response
		}
	}

	// 10.优惠券的发放(发放 + 标记已用)
	if prizeGift.Gtype == conf.GtypeCodeDiff {
		code := utils.PrizeCodeDiff(prizeGift.Id, c.CodeService)
		if code == "" {
			response["code"] = 2004
			response["msg"] = "没有中奖，再来一次"
			return response
		}

		// 否则发奖
		prizeGift.Gdata = code
	}

	// 11.纪录中奖信息
	result := &models.GiftRecord{
		GiftId:     prizeGift.Id,
		GiftName:   prizeGift.Title,
		GiftType:   prizeGift.Gtype,
		Uid:        loginUser.UID,
		Username:   loginUser.Username,
		PrizeCode:  prizeCode,
		GiftData:   prizeGift.Gdata,
		SysStatus:  0,
		SysCreated: comm.NowUnix(),
		SysIp:      clientIp,
	}
	err := c.ResultService.Insert(result)
	if err != nil {
		log.Println("ResultService.Insert error", result)
		response["code"] = 2004
		response["msg"] = "没有中奖，再来一次"
		return response
	}

	// 如果中了大奖，需要把这个用户黑名单一会
	if prizeGift.Gtype == conf.GtypeGiftLarge {
		c.InsertToBlack(clientIp, loginUser, userBlack, ipBlack)
	}

	// 12.返回中奖信息
	response["gift"] = prizeGift

	return response
}
